﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Threading;
using System.Windows.Forms;

using System.Xml.Serialization;
using System.IO;
using System.Collections;
using System.Xml;


namespace _3D_FileExplorer
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Fe : Microsoft.Xna.Framework.Game
    {
        public static GraphicsDeviceManager graphics;
        public static SpriteBatch spriteBatch;
        public static Camera camera;
        public static Panel canvas;
        public static MenuStrip menu;
        public static int mouseWheelState;
        public static bool leftButtonClick = false;
        public static bool rightButtonClick = false;
        public static bool doubleClick = false;
        public static bool menuIsActive = false;
        public static MainForm form;
        public static Parameters par;
        public static TexturesDefinition td;
        DrawGraphicsTree graphicsTree;
        DrawBoundingCubes boundingCubes;
        DrawLeafs leafs;
        Interface gInterface;
        Cursor cursor;
        KeyboardControl kbc;
        public static BasicEffect effect;
        public static ContentManager content;
        FileSystemDataProvider dp;





        public Fe(MainForm mForm, Panel pb, MenuStrip mMenu)
        {
            menu = mMenu;
            form = mForm;
            Form xnaWindow = (Form)Control.FromHandle((this.Window.Handle));
            graphics = new GraphicsDeviceManager(this);
            canvas = pb;
            Mouse.WindowHandle = pb.Handle;
            content = Content;
            Content.RootDirectory = "Content";
            content.RootDirectory = "Content";
            form.Panel.Resize += new EventHandler(Panel_Resize);
            graphics.PreferredBackBufferWidth = canvas.Width;
            graphics.PreferredBackBufferHeight = canvas.Height;

            #region EVENTS
            graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
            form.Panel.Resize += new EventHandler(Panel_Resize);
            xnaWindow.GotFocus += new EventHandler(xnaWindow_GotFocus);
            form.MouseWheel += new MouseEventHandler(Panel_MouseWheel);
            form.PathTextBox.KeyDown += new KeyEventHandler(TextBox_KeyDown);
            form.PathTextBox.MouseClick += new MouseEventHandler(TextBox_MouseClick);
            canvas.MouseDoubleClick += new MouseEventHandler(Panel_DoubleClick);
            canvas.MouseClick += new MouseEventHandler(Panel_MouseClick);
            //canvas.MouseUp += new MouseEventHandler(Panel_MouseUP);
            menu.MenuActivate += new EventHandler(Menu_MenuActivate);
            menu.MenuDeactivate += new EventHandler(Menu_MenuDeactivate);
            #endregion

        }

        void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
        {
            e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = form.Panel.Handle;
        }
        void xnaWindow_GotFocus(object sender, EventArgs e)
        {
            ((Form)sender).Visible = false;
            form.TopMost = false;
            canvas.Focus();
        }
        void Panel_Resize(object sender, EventArgs e)
        {

            if (form.Height > 59)
            {
                GraphicsDevice.PresentationParameters.BackBufferHeight = form.Panel.Height;
                GraphicsDevice.PresentationParameters.BackBufferWidth = form.Panel.Width;
                GraphicsDevice.Reset(GraphicsDevice.PresentationParameters);
                GraphicsDevice.VertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionColorTexture.VertexElements);
                camera.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)Fe.canvas.Width / (float)Fe.canvas.Height, 1, 100000);
            }
        }

        void Panel_MouseWheel(object sender, MouseEventArgs e)
        {
            mouseWheelState += e.Delta;
            Console.WriteLine(mouseWheelState);
        }

        void Panel_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                leftButtonClick = true;
            }

            if (e.Button == MouseButtons.Right)
            {
                rightButtonClick = true;
            }
        }

        void Panel_MouseUP(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                leftButtonClick = false;
            }

            if (e.Button == MouseButtons.Right)
            {
                rightButtonClick = false;
            }
        }

        void Panel_DoubleClick(object sender, MouseEventArgs e)
        {

            doubleClick = true;

        }

        void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == '\r')
            {
                canvas.Focus();
                if (dp.VerifyPath(form.PathTextBox.Text))
                {
                    DrawGraphicsTree.CreateNewThread(GraphicsDevice, form.PathTextBox.Text, par.defaultBranchLevel, true);
                }
                else
                {
                    form.PathTextBox.ForeColor = System.Drawing.Color.Red;
                    form.PathTextBox.Text = "Directory does not exist!!!";
                }
            }
        }

        void TextBox_MouseClick(object sender, MouseEventArgs e)
        {
            //form.PathTextBox.Select(0, form.PathTextBox.TextLength);
            form.PathTextBox.ForeColor = System.Drawing.Color.Black;
        }

        void Menu_MenuActivate(object sender, EventArgs e)
        {
            menuIsActive = true;
        }
        void Menu_MenuDeactivate(object sender, EventArgs e)
        {
            menuIsActive = false;
        }








        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            effect = new BasicEffect(GraphicsDevice, null);
            //par = new Parameters();
            //Parameters.SerializeToXML(par);
            par = Parameters.DeserializeFromXML();
            //td = new TexturesDefinition();
            //TexturesDefinition.SerializeToXML(td);
            td = TexturesDefinition.DeserializeFromXML();
            //td = new TexturesDefinition(td.texDef);
            dp = new FileSystemDataProvider();
            // Initialize camere
            camera = new Camera(this, new Vector3(0, 0, 30),
            Vector3.Zero, Vector3.Up);
            Components.Add(camera);

            //Initialize Graphics tree component
            graphicsTree = new DrawGraphicsTree(this);
            Components.Add(graphicsTree);

            //Initialize Boundingcubes component
            //boundingCubes = new DrawBoundingCubes(this);
            //Components.Add(boundingCubes);

            //Initialize interface
            gInterface = new Interface(this, Content, camera);
            Components.Add(gInterface);
            //Initialize Cursor component
            cursor = new Cursor(this, Content);
            Components.Add(cursor);
            base.Initialize();

        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.

            spriteBatch = new SpriteBatch(GraphicsDevice);


        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime Time)
        {
            // Allows the game to exit
            // TODO: Add your update logic here
            base.Update(Time);
        }



        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            GraphicsDevice.RenderState.CullMode = CullMode.None;
            GraphicsDevice.RenderState.AlphaBlendEnable = false;
            GraphicsDevice.RenderState.DepthBufferEnable = true;
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }


    }
}
